1 From 3ac592da09acb47b728ef320e9fecde55c8e0824 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Fri, 26 Jun 2020 11:51:05 +0100
4 Subject: [PATCH] brcmfmac: Prefer a ccode from OTP over nvram file
6 Allow the nvram file to set a default ccode (regulatory domain) without
7 overriding one set in OTP.
9 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
11 .../broadcom/brcm80211/brcmfmac/cfg80211.c | 39 +++++++++++++------
12 .../broadcom/brcm80211/brcmfmac/firmware.c | 21 +++++++++-
13 2 files changed, 47 insertions(+), 13 deletions(-)
15 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
16 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
18 #include <linux/etherdevice.h>
19 #include <linux/module.h>
20 #include <linux/vmalloc.h>
21 +#include <linux/ctype.h>
22 #include <net/cfg80211.h>
23 #include <net/netlink.h>
24 #include <uapi/linux/if_arp.h>
25 @@ -8223,31 +8224,45 @@ static void brcmf_cfg80211_reg_notifier(
26 struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
27 struct brcmf_pub *drvr = cfg->pub;
28 struct brcmf_fil_country_le ccreq;
33 - /* The country code gets set to "00" by default at boot, ignore */
34 - if (req->alpha2[0] == '0' && req->alpha2[1] == '0')
35 + err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
37 + bphy_err(drvr, "Country code iovar returned err = %d\n", err);
41 + /* The country code gets set to "00" by default at boot - substitute
42 + * any saved ccode from the nvram file unless there is a valid code
45 + alpha2 = req->alpha2;
46 + if (alpha2[0] == '0' && alpha2[1] == '0') {
47 + extern char saved_ccode[2];
49 + if ((isupper(ccreq.country_abbrev[0]) &&
50 + isupper(ccreq.country_abbrev[1])) ||
53 + alpha2 = saved_ccode;
54 + pr_debug("brcmfmac: substituting saved ccode %c%c\n",
55 + alpha2[0], alpha2[1]);
58 /* ignore non-ISO3166 country codes */
59 for (i = 0; i < 2; i++)
60 - if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
61 + if (alpha2[i] < 'A' || alpha2[i] > 'Z') {
62 bphy_err(drvr, "not an ISO3166 code (0x%02x 0x%02x)\n",
63 - req->alpha2[0], req->alpha2[1]);
64 + alpha2[0], alpha2[1]);
68 brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator,
69 - req->alpha2[0], req->alpha2[1]);
71 - err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
73 - bphy_err(drvr, "Country code iovar returned err = %d\n", err);
76 + alpha2[0], alpha2[1]);
78 - err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq);
79 + err = brcmf_translate_country_code(ifp->drvr, alpha2, &ccreq);
83 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
84 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
86 #include <linux/firmware.h>
87 #include <linux/module.h>
88 #include <linux/bcm47xx_nvram.h>
89 +#include <linux/ctype.h>
93 @@ -32,6 +33,8 @@ enum nvram_parser_state {
97 +char saved_ccode[2] = {};
100 * struct nvram_parser - internal info for parser.
102 @@ -562,11 +565,27 @@ static int brcmf_fw_request_nvram_done(c
108 + char *ccode = strnstr((char *)data, "ccode=", data_len);
109 + /* Ensure this is a whole token */
110 + if (ccode && ((void *)ccode == (void *)data || isspace(ccode[-1]))) {
111 + /* Comment out the line */
114 + if (isupper(ccode[0]) && isupper(ccode[1]) &&
115 + isspace(ccode[2])) {
116 + pr_debug("brcmfmac: intercepting ccode=%c%c\n",
117 + ccode[0], ccode[1]);
118 + saved_ccode[0] = ccode[0];
119 + saved_ccode[1] = ccode[1];
123 nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
124 fwctx->req->domain_nr,
129 if (free_bcm47xx_nvram)
130 bcm47xx_nvram_release_contents(data);